package qc.module.platform.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import qc.common.core.enums.FileTypeEnum;
import qc.common.core.exception.QCPromptException;
import qc.common.core.utils.DateUtil;
import qc.common.core.utils.FileTypeUtil;
import qc.module.platform.dto.file.FileInfoDto;
import qc.module.platform.dto.file.FileQueryConditionDto;
import qc.module.platform.entity.QcFiles;
import qc.module.platform.mapper.FileMapper;
import qc.module.platform.repository.QcFilesRepository;

import java.util.Date;
import java.util.List;

/**
 * FileService
 *
 * @author QuCheng Tech
 * @since 2023/6/8
 */
@Service
public class FileService {
    private QcFilesRepository repository;

    @Autowired
    public void setQcFilesRepository(QcFilesRepository repository) {
        this.repository = repository;
    }

    /***
     * 保存文件信息，根据传入的文件id自动判断是新增还是修改；返回文件ID
     *
     * @param id 文件ID，新增时传入0
     * @param title 文件显示使用的标题文字，不包含扩展名；为空时使用原文件名或名称
     * @param path 文件所在目录
     * @param name 文件名，不包含目录和扩展名，实际服务器上存放的文件名；可能是UUID
     * @param extension 扩展名，不包含点符号
     * @param system 系统名称，可以为空；建议对应module的名称
     * @param module 模块名称，可以为空；
     * @param size 文件大小，单位：MB
     * @return int 文件ID
     * @author QuCheng Tech
     * @since 2025/3/6
     */
    public int save(int id, String title, String path, String name, String extension, String system, String module, double size) throws QCPromptException {
        boolean isAdd = false;
        //判断ID是否有效，无效表示新增，生成一个文件ID
        //如传入的文件ID有效，但文件信息不存在，也作为新增
        if (id < 0x1 || hasIdExist(id) == false) {
            //ID无效，生成一个文件ID,获取数据库中的最大id+1后赋值
            isAdd = true;
            id = genereateId();
        }

        //根据文件扩展名获取对应的枚举
        FileTypeEnum fileTypeEnum = FileTypeUtil.getByExtension(extension);

        if (isAdd == true) {
            //新增
            QcFiles en = new QcFiles();
            en.setId(id);
            if (!StringUtils.isBlank(title))
                en.setTitle(title);
            if (!StringUtils.isBlank(name))
                en.setName(name);
            if (!StringUtils.isBlank(system))
                en.setSys(system);
            if (!StringUtils.isBlank(module))
                en.setModule(module);
            if (!StringUtils.isBlank(path))
                en.setPath(path);
            if (!StringUtils.isBlank(extension))
                en.setExtension(extension);
            //判断文件类型
            en.setType(fileTypeEnum);

            en.setSize(size);
            //默认赋值：时间、浏览次数、下载次数
            en.setTm(DateUtil.getNowDate());
            en.setVcount(0x0);
            en.setDcount(0x0);

            if (repository.insert(en) < 0x1)
                throw new QCPromptException("保存文件信息到数据库失败");
        } else {
            //修改，修改时不对文件的上传时间、浏览次数、下载次数进行更新
            LambdaUpdateWrapper<QcFiles> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(QcFiles::getId, id)
                    .set(QcFiles::getTitle, title)
                    .set(QcFiles::getName, name)
                    .set(QcFiles::getSys, system)
                    .set(QcFiles::getModule, module)
                    .set(QcFiles::getPath, path)
                    .set(QcFiles::getExtension, extension)
                    .set(QcFiles::getType, fileTypeEnum)
                    .set(QcFiles::getSize, size);

            repository.update(null, wrapper);
        }

        return id;
    }

    /**
     * 获取指定ID的文件信息
     *
     * @param fileId 文件ID
     * @return 文件实体类
     * @author QuCheng Tech
     * @since 2023/6/8
     */
    public QcFiles get(int fileId) throws QCPromptException {
        if (fileId < 0x1)
            throw new QCPromptException("文件ID无效");

        QcFiles file = repository.selectById(fileId);

        if (file == null)
            throw new QCPromptException("指定ID的文件信息不存在");

        return file;
    }

    /**
     * 获取指定ID的文件信息，不包含内容
     *
     * @param id:文件id
     * @return FileInfoDto 获取指定文件信息存在返回文件信息，不存在返回内容null
     * @author QcCheng Tech
     * @date 2023/10/18
     */
    public FileInfoDto getFile(int id) {
        //查询条件
        LambdaQueryWrapper<QcFiles> wrapper = new LambdaQueryWrapper<>();
        //指定查询内容
        wrapper.select(QcFiles::getId, QcFiles::getTitle, QcFiles::getName, QcFiles::getExtension, QcFiles::getType, QcFiles::getSize, QcFiles::getTm, QcFiles::getVcount, QcFiles::getDcount,QcFiles::getPath);
        //查询条件
        wrapper.eq(QcFiles::getId, id);
        QcFiles qcFiles = repository.selectOne(wrapper);
        if (qcFiles == null)
            return null;
        return FileMapper.MAPPER.toDto(qcFiles);
    }

    /**
     * 查看指定ID的文件信息，浏览次数+1
     *
     * @param fileId 文件ID
     * @return 文件实体类
     * @author QuCheng Tech
     * @since 2023/6/8
     */
    public QcFiles view(int fileId) throws QCPromptException {
        QcFiles en = get(fileId);

        if (en != null) {
            LambdaUpdateWrapper<QcFiles> wrapper = new LambdaUpdateWrapper<>();
            //次数+1
            wrapper.setSql("vcount=vcount+1");
            wrapper.eq(QcFiles::getId, fileId);

            repository.update(null, wrapper);
        }

        return en;
    }

    /**
     * 下载指定ID的文件，下载次数+1
     *
     * @param fileId 文件ID
     * @return 文件实体类
     * @author QuCheng Tech
     * @since 2023/6/8
     */
    public QcFiles download(int fileId) throws QCPromptException {
        QcFiles en = get(fileId);

        if (en != null) {
            LambdaUpdateWrapper<QcFiles> wrapper = new LambdaUpdateWrapper<>();
            //次数+1
            wrapper.setSql("dcount=dcount+1");
            wrapper.eq(QcFiles::getId, fileId);

            repository.update(null, wrapper);
        }

        return en;
    }

    /***
     * 查询文件
     *
     * @param condition 查询条件
     * @return java.util.List<qc.module.platform.dto.file.FileInfoDto>
     * @author QuCheng Tech
     * @since 2023/8/14
     */
    public List<FileInfoDto> query(FileQueryConditionDto condition) throws QCPromptException {
        if (condition == null)
            throw new QCPromptException("查询文件的条件不能为空");
        if (StringUtils.isBlank(condition.getSys()))
            throw new QCPromptException("查询文件的指定的所属系统不能为空");
        if (StringUtils.isBlank(condition.getModule()))
            throw new QCPromptException("查询文件的指定的所属模块不能为空");
        if (StringUtils.isBlank(condition.getBegintm()))
            throw new QCPromptException("查询文件的上传开始时间不能为空");
        if (StringUtils.isBlank(condition.getEndtm()))
            throw new QCPromptException("查询文件的上传截止时间不能为空");

        Date beginTime = null;
        try {
            beginTime = DateUtil.parseDate(condition.getBegintm());
        } catch (Exception e) {
            throw new QCPromptException("查询文件的上传开始时间转换错误");
        }
        Date endTime = null;
        try {
            endTime = DateUtil.parseDate(condition.getEndtm());
        } catch (Exception e) {
            throw new QCPromptException("查询文件的上传截止时间转换错误");
        }
        if (beginTime.after(endTime))
            throw new QCPromptException("查询文件的上传开始时间不能大于截止时间");

        FileTypeEnum fileTypeEnum = getFileTypeEnum(condition.getType());

        LambdaQueryWrapper<QcFiles> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QcFiles::getSys, condition.getSys());
        wrapper.eq(QcFiles::getModule, condition.getModule());
        wrapper.ge(QcFiles::getTm, beginTime);
        wrapper.le(QcFiles::getTm, endTime);
        if (fileTypeEnum != FileTypeEnum.UN_KNOW)
            wrapper.eq(QcFiles::getType, fileTypeEnum);

        wrapper.orderByAsc(QcFiles::getTm);

        List<QcFiles> ens = repository.selectList(wrapper);

        if (ens != null && ens.size() > 0x0) {
            return FileMapper.MAPPER.toDtoList(ens);
        }

        return null;
    }

    /**
     * 判断指定的ID是否存在
     *
     * @param id 分类ID
     * @return true表示已存在，false表示不存在
     * @author QuCheng Tech
     * @since 2023/5/28
     */
    public boolean hasIdExist(int id) {
        LambdaQueryWrapper<QcFiles> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QcFiles::getId, id);

        QcFiles en = repository.selectOne(wrapper);
        if (en != null)
            return true;

        return false;
    }

    /**
     * 生成记录ID，获取数据库表中的最大记录ID+1
     *
     * @return 生成记录ID
     * @author QuCheng Tech
     * @since 2023/5/28
     */
    int genereateId() {
        int maxRecordId = getMaxId();
        return maxRecordId + 1;
    }

    /**
     * 获取数据库表中的最大ID值，没有记录时返回0
     *
     * @return 返回数据库表中的最大ID值
     * @author QuCheng Tech
     * @since 2023/5/28
     */
    int getMaxId() {
        LambdaQueryWrapper<QcFiles> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(QcFiles::getId);
        wrapper.orderByDesc(QcFiles::getId);
        QcFiles en = repository.selectOne(wrapper);
        if (en != null)
            return en.getId();

        return 0x0;
    }

    FileTypeEnum getFileTypeEnum(int type) {
        if (type >= 0x0) {
            for (FileTypeEnum item : FileTypeEnum.values()) {
                if (item.getIndex() == type) {//判断序号使用getIndex，判断内容使用getName
                    return item;
                }
            }
        }

        return FileTypeEnum.UN_KNOW;
    }
}
    
